﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;

using TInput = System.String;
using TOutput = LevelLibrary.Level;

namespace LevelContentPipelineExtension
{
    [ContentProcessor(DisplayName = "Level Processor")]
    public class LevelProcessor : ContentProcessor<TInput, TOutput>
    {
        public override TOutput Process(TInput input, ContentProcessorContext context)
        {
            string[] lines = input.Split(new char[] {'\n'});
            int rows = Convert.ToInt32(lines[0]);
            int columns = Convert.ToInt32(lines[1]);

            int[,] levelData = new int[rows, columns];

            for (int row = 0; row < rows; row++)
            {
                string[] values = lines[row + 2].Split(new char[] { ' ' });
                for (int column = 0; column < columns; column++)
                {
                    levelData[row, column] = Convert.ToInt32(values[column]);
                }
            }

          //wall cleaning
            if((levelData[0,columns-1] == 1)&&
               ((levelData[0, columns-2] == 1) || (levelData[0, columns-2] == 0)) &&
               ((levelData[1, columns-2] == 1) || (levelData[1, columns-2] == 0)) &&
               ((levelData[1, columns-1] == 1) || (levelData[1, columns-1] == 0)))
            {
                levelData[0,columns-1] = 0;
            }

            if ((levelData[rows-1, 0] == 1) &&
               ((levelData[rows - 2, 1] == 1) || (levelData[rows - 2, 1] == 0)) &&
               ((levelData[rows - 1, 1] == 1) || (levelData[rows - 1, 1] == 0)) &&
               ((levelData[rows - 2, 0] == 1) || (levelData[rows - 2, 0] == 0)))
            {
                levelData[rows - 1, 0] = 0;
            }

            if ((levelData[rows - 1, columns - 1] == 1) &&
               ((levelData[rows - 2, columns -2] == 1) || (levelData[rows - 2, columns -2] == 0)) &&
               ((levelData[rows - 1, columns -2] == 1) || (levelData[rows - 1, columns -2] == 0)) &&
               ((levelData[rows - 2, columns -1] == 1) || (levelData[rows - 2, columns -1] == 0)))
            {
                levelData[rows - 1, columns - 1] = 0;
            }

            if ((levelData[0, 0] == 1) &&
               ((levelData[0, 1] == 1) || (levelData[0, 1] == 0)) &&
               ((levelData[1, 1] == 1) || (levelData[1, 1] == 0)) &&
               ((levelData[1, 0] == 1) || (levelData[1, 0] == 0)))
            {
                levelData[0, 0] = 0;
            }

            for (int row = 1; row < rows-1; row++)
            {
                //left
                if ((levelData[row, 0] == 1) &&
                        ((levelData[row - 1, 0] == 1) || (levelData[row - 1, 0] == 0)) &&       
                        ((levelData[row - 1, 1] == 1) || (levelData[row - 1, 1] == 0)) &&           
                        ((levelData[row, 1] == 1) || (levelData[row, 1] == 0)) &&           
                        ((levelData[row + 1, 1] == 1) || (levelData[row + 1, 1] == 0)) &&       
                        ((levelData[row + 1, 0] == 1) || (levelData[row + 1, 0] == 0)))                                 
                {
                    levelData[row, 0] = 0;
                }

                //right
                if ((levelData[row, columns - 1] == 1) &&
                        ((levelData[row - 1, columns - 1] == 1) || (levelData[row - 1, columns - 1] == 0)) &&
                        ((levelData[row - 1, columns - 2] == 1) || (levelData[row - 1, columns - 2] == 0)) &&
                        ((levelData[row, columns - 2] == 1) || (levelData[row, columns - 2] == 0)) &&
                        ((levelData[row + 1, columns - 2] == 1) || (levelData[row + 1, columns - 2] == 0)) &&
                        ((levelData[row + 1, columns - 1] == 1) || (levelData[row + 1, columns - 1] == 0)))
                {
                    levelData[row, columns - 1] = 0;
                }
                
                for (int column = 1; column < columns-1; column++)
                {
                    //top
                    if ((levelData[0, column] == 1) &&
                        ((levelData[0, column - 1] == 1) || (levelData[0, column - 1] == 0)) &&
                        ((levelData[0, column + 1] == 1) || (levelData[0, column + 1] == 0)) &&
                        ((levelData[1, column - 1] == 1) || (levelData[1, column - 1] == 0)) &&
                        ((levelData[1, column + 1] == 1) || (levelData[1, column + 1] == 0)) &&
                        ((levelData[1, column] == 1) || (levelData[1, column] == 0)))
                    {
                        levelData[0, column] = 0;
                    }

                    //bottom
                    if ((levelData[rows-1, column] == 1) &&
                        ((levelData[rows - 1, column - 1] == 1) || (levelData[rows - 1, column - 1] == 0)) &&
                        ((levelData[rows - 1, column + 1] == 1) || (levelData[rows - 1, column + 1] == 0)) &&
                        ((levelData[rows - 2, column - 1] == 1) || (levelData[rows - 2, column - 1] == 0)) &&
                        ((levelData[rows - 2, column + 1] == 1) || (levelData[rows - 2, column + 1] == 0)) &&
                        ((levelData[rows - 2, column] == 1) || (levelData[rows - 2, column] == 0)))
                    {
                        levelData[rows - 1, column] = 0;
                    }

                    //middle
                    if ((levelData[row,column]==1)&&
                       ((levelData[row - 1, column - 1] == 1) || (levelData[row - 1, column - 1] == 0)) &&       //left-top
                       ((levelData[row - 1, column] == 1) || (levelData[row - 1, column] == 0)) &&           //top
                       ((levelData[row - 1, column + 1] == 1) || (levelData[row - 1, column + 1] == 0)) &&       //top-right
                       ((levelData[row, column + 1] == 1) || (levelData[row, column + 1] == 0)) &&           //right
                       ((levelData[row + 1, column + 1] == 1) || (levelData[row + 1, column + 1] == 0)) &&       //right-bottom
                       ((levelData[row + 1, column] == 1) || (levelData[row + 1, column] == 0)) &&           //bottom
                       ((levelData[row + 1, column - 1] == 1) || (levelData[row + 1, column - 1] == 0)) &&       //bottom-left
                       ((levelData[row, column - 1] == 1) || (levelData[row, column - 1] == 0)))        //left
                    {
                        levelData[row, column] = 0;
                    }
                }
            }

            //wall cleaning - end

            //wall declaring
            //if specified wall connects with another, connecting bits are set.
            //connecting bits:
            // |...|U |D|L|R|x|x|x|x|x|x|x|x|
            //     11 10 9 8 7 6 5 4 3 2 1 0
            //U - upper
            //D - lower
            //L - left
            //R - right

            if ((levelData[0, columns - 1]&1) == 1)
            {
                levelData[0, columns - 1] = ((((levelData[0, columns - 2] & 1) << 9) | ((levelData[1, columns - 1] & 1) << 10))) | 1;
            }

            if ((levelData[rows - 1, 0]&1) == 1) 
            {
                levelData[rows - 1, 0] = (((levelData[rows - 2, 0] & 1) << 11) | ((levelData[rows - 1, 1] & 1) << 8)) | 1;
            }

            if ((levelData[rows - 1, columns - 1]&1) == 1) 
            {
                levelData[rows - 1, columns - 1] = (((levelData[rows - 2, columns - 1] & 1) << 11) | ((levelData[rows - 1, columns - 2] & 1) << 9)) | 1;
            }

            if ((levelData[0, 0]&1) == 1) 
            {
                levelData[0, 0] = (((levelData[0, 1]&1) << 8) | ((levelData[1, 0] & 1) << 10)) | 1;
            }

            for (int row = 1; row < rows - 1; row++)
            {
                //left
                if ((levelData[row, 0]&1) == 1) 
                {
                    levelData[row, 0] = (((levelData[row - 1, 0] & 1) << 11) | ((levelData[row + 1, 0]&1) << 10) | ((levelData[row, 1]&1) << 8)) | 1;
                }

                //right
                if ((levelData[row, columns - 1]&1) == 1) 
                {
                    levelData[row, columns - 1] = (((levelData[row - 1, columns - 1] & 1) << 11) | ((levelData[row + 1, columns - 1] & 1) << 10) | ((levelData[row, columns - 2] & 1) << 9)) | 1;
                }

                for (int column = 1; column < columns - 1; column++)
                {
                    //top
                    if ((levelData[0, column]&1) == 1) 
                    {
                        levelData[0, column] = (((levelData[0, column - 1] & 1) << 9) | ((levelData[0, column + 1] & 1) << 8) | ((levelData[1, column]&1) << 10)) | 1;
                    }

                    //bottom
                    if ((levelData[rows - 1, column]&1) == 1)
                    {
                        levelData[rows - 1, column] = (((levelData[rows - 1, column - 1] & 1) << 9) | ((levelData[rows - 1, column + 1] &1)<< 8) | ((levelData[rows - 2, column]&1) << 11)) | 1;
                    }

                    //middle
                    if ((levelData[row, column]&1) == 1) 
                    {
                        levelData[row, column] = (((levelData[row - 1, column]&1) << 11) | ((levelData[row + 1, column]&1) << 10) | ((levelData[row, column - 1]&1) << 9) | ((levelData[row, column + 1]&1) << 8))|1;
                    }
                }
            }
            //wall declaring - end

            return new LevelLibrary.Level(levelData);
        }
    }
}